﻿/*
 * This software is the confidential and proprietary
 * information of NetBay
 * Such confidential information should not be disclosed
 * NetBay copyright(c) 2010
 */

#region Using
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml.Serialization;
#endregion

namespace NetBay.Core.Tools
{
    /// <summary>
    /// 
    /// </summary>
    public static class FileSerializer
    {

        private static object _Lock = new object();

        #region Serialize

        /// <summary> 
        /// Serialize an object and store it in a file. 
        /// </summary> 
        /// <param name="mode">The instance of an object to serialize</param> 
        /// <param name="instance">The instance of an object to serialize.</param> 
        /// <param name="filePath">The location on disk.</param> 
        /// <returns>A serialized MemoryStream.</returns> 
        public static void Serialize(SerializeMode mode, object instance, string filePath)
        {
            using (FileStream fs = new FileStream(filePath, FileMode.Create))
            {
                MemoryStream stream = Serialize(mode, instance);
                byte[] buffer = stream.ToArray();
                fs.Write(buffer, 0, buffer.Length);
                fs.Flush();
            }
        }


        /// <summary> 
        /// Serializes any instances of any objects. 
        /// </summary> 
        /// <param name="mode">The instance of an object to serialize</param> 
        /// <param name="instance">The instance of an object to serialize.</param> 
        /// <returns>A serialized MemoryStream.</returns> 
        public static MemoryStream Serialize(SerializeMode mode, object instance)
        {
            if (instance == null)
                throw new ArgumentNullException("The instance object is null.");

            lock (_Lock)
            {
                MemoryStream stream = new MemoryStream();
                switch (mode)
                {
                    case SerializeMode.Xml:
                        SerializeXml(ref stream, ref instance);
                        return stream;

                    default:
                        SerializeBinary(ref stream, ref instance);
                        return stream;
                }
            }
        }

        private static void SerializeBinary(ref MemoryStream stream, ref object instance)
        {
            BinaryFormatter bfor = new BinaryFormatter();
            bfor.Serialize(stream, instance);
            bfor = null;

        }


        private static void SerializeXml(ref MemoryStream stream, ref object instance)
        {
            XmlSerializer ser = new XmlSerializer(instance.GetType());
            XmlSerializerNamespaces xsn = new XmlSerializerNamespaces();
            xsn.Add(string.Empty, null);
            ser.Serialize(stream, instance, xsn);
            ser = null;
        }

        #endregion

        #region Deserialize

        /// <summary> 
        /// Deserialize an object from a byte array 
        /// </summary> 
        /// <param name="mode">The mode to deserialize the object.</param> 
        /// <param name="instance">Specify an instance of an object to deserialize.</param> 
        /// <param name="buffer">A byte array containing the serialized object, that needs 
        /// to be deserialized</param> 
        /// <returns>A deserialized object.</returns> 
        public static T Deserialize<T>(SerializeMode mode, T instance, byte[] buffer)
        {
            if (buffer == null)
                throw new ArgumentNullException("The byte array is null.");

            lock (_Lock)
            {
                switch (mode)
                {
                    case SerializeMode.Xml:
                        return DeserializeXml<T>(instance, buffer);

                    default:
                        return DeserializeBinary<T>(instance, buffer);
                }
            }
        }

        /// <summary> 
        /// Deserialize an object from a location on disk or network. 
        /// </summary> 
        /// <param name="mode">The mode to deserialize the object.</param> 
        /// <param name="instance">Specify an instance of an object to deserialize.</param> 
        /// <param name="filePath">The path to the serialized object.</param> 
        /// <returns>A deserialized object.</returns> 
        public static T Deserialize<T>(SerializeMode mode, T instance, string filePath)
        {
            byte[] buffer = null;

            try
            {
                using (FileStream fs = new FileStream(filePath, FileMode.Open))
                {
                    buffer = new byte[fs.Length];
                    fs.Read(buffer, 0, buffer.Length);
                    return Deserialize<T>(mode, instance, buffer);
                }
            }
            finally
            {
                buffer = null;
            }
        }

        /// <summary> 
        /// Deserializes an object from a byte array 
        /// </summary> 
        private static T DeserializeXml<T>(T instance, byte[] buffer)
        {
            using (MemoryStream stream = new MemoryStream(buffer))
            {
                XmlSerializer ser = new XmlSerializer(typeof(T));
                instance = (T)ser.Deserialize(stream);
                return instance;
            }
        }

        /// <summary> 
        /// Deserializes the object from a byte array. 
        /// </summary> 
        /// <param name="instance">Specify an instance of an object to deserialize.</param> 
        /// <param name="array">A serialized byte array</param> 
        private static T DeserializeBinary<T>(T instance, byte[] array)
        {
            BinaryFormatter bf;
            MemoryStream ms = null;
            try
            {
                ms = new MemoryStream(array);
                {
                    bf = new BinaryFormatter();
                    instance = (T)bf.Deserialize(ms);
                    return instance;
                }
            }
            finally
            {
                bf = null;
                if (ms != null) ms.Close();
                ms = null;
            }
        }



        /// <summary>
        /// Sérialize un dictionnaire d'index en binaire
        /// </summary>
        /// <param name="instance"></param>
        /// <returns></returns>
        public static  string SerializeBinaryIndex( object instance)
        {

            BinaryFormatter bf = new BinaryFormatter();
            MemoryStream ms = new MemoryStream();
            bf.Serialize(ms, instance);
            byte[] buff = ms.ToArray();
            ms.Close();
            return Convert.ToBase64String(buff);
        }

       /// <summary>
       /// Désérialize le dictionnaire d'index
       /// </summary>
       /// <typeparam name="T"></typeparam>
       /// <param name="val"></param>
       /// <returns></returns>
        public static T DeSerializeBinaryIndex<T>(string val)

        {
            byte[] buff = Convert.FromBase64String(val);
            BinaryFormatter bf = new BinaryFormatter();
            MemoryStream ms = new MemoryStream(buff);
            T result = (T)bf.Deserialize(ms);
            ms.Close();
            return result;
        }



        #endregion



        #region Enumeration

        /// <summary> 
        /// The type of serialization. 
        /// </summary> 
        public enum SerializeMode
        {
            /// <summary>Will serialize to a binary format.</summary> 
            Binary,
            /// <summary>Will serialize to an XML format.</summary> 
            Xml
        }

        #endregion


        //    /// <summary>
        //    /// Serializes the specified filename.
        //    /// </summary>
        //    /// <typeparam name="T">Generic type which implements the ISerializable interface</typeparam>
        //    /// <param name="p_sFilename">The filename.</param>
        //    /// <param name="p_oObjectToSerialize">The object to serialize.</param>
        //    public static void Serialize<T>(string p_sFilename, T p_oObjectToSerialize)
        //    {
        //        if (p_oObjectToSerialize == null)
        //            throw new ArgumentNullException("objectToSerialize cannot be null");
        //        Stream stream = null;
        //        try
        //        {
        //            stream = File.Open(p_sFilename, FileMode.Create);
        //            BinaryFormatter bFormatter = new BinaryFormatter();
        //            bFormatter.Serialize(stream, p_oObjectToSerialize);
        //        }
        //        finally
        //        {
        //            if (stream != null)
        //            {
        //                stream.Close();
        //                stream.Dispose();
        //            }

        //        }
        //    }

        //    /// <summary>
        //    /// Deserializes the specified filename.
        //    /// </summary>
        //    /// <typeparam name="T">Generic type which implements the ISerializable interface</typeparam>
        //    /// <param name="p_sFilename">The filename.</param>
        //    /// <returns></returns>
        //    public static T Deserialize<T>(string p_sFilename)
        //    {
        //        T objectToSerialize = default(T);
        //        Stream stream = null;
        //        try
        //        {
        //            stream = File.Open(p_sFilename, FileMode.Open);
        //            BinaryFormatter bFormatter = new BinaryFormatter();
        //            objectToSerialize = (T)bFormatter.Deserialize(stream);
        //        }
        //        catch (Exception ex)
        //        {
        //            LogManager.GetBusinessLogger().LogErrorFormat("Unable to Deserialize the file {0} in object type {1}. Exception : {2}", p_sFilename, typeof(T).Name, ex);
        //        }
        //        finally
        //        {

        //            if (stream != null)
        //            {
        //                stream.Close();
        //                stream.Dispose();
        //            }
        //        }
        //        return objectToSerialize;
        //    }

        //    /// <summary>
        //    /// XMLs the serialize.
        //    /// </summary>
        //    /// <typeparam name="T"></typeparam>
        //    /// <param name="p_sFilename">The filename.</param>
        //    /// <param name="p_oObjectToSerialize">The object to serialize.</param>
        //    /// <param name="p_bCreateIfNotExist">if set to <c>true</c> [create if not exist].</param>
        //    public static void XMLSerialize<T>(string p_sFilename, T p_oObjectToSerialize, bool p_bCreateIfNotExist)
        //    {
        //        if (p_bCreateIfNotExist)
        //        {
        //            FileTools.CreateFile(p_sFilename, true);
        //        }
        //        XMLSerialize<T>(p_sFilename, p_oObjectToSerialize);
        //    }

        //    /// <summary>
        //    /// Serializes the specified filename.
        //    /// </summary>
        //    /// <typeparam name="T">Generic type which implements the ISerializable interface</typeparam>
        //    /// <param name="p_sFilename">The filename.</param>
        //    /// <param name="p_oObjectToSerialize">The object to serialize.</param>
        //    public static void XMLSerialize<T>(string p_sFilename, T p_oObjectToSerialize)
        //    {
        //        if (p_oObjectToSerialize == null)
        //            throw new ArgumentNullException("ObjectToSerialize cannot be null");

        //        if (!File.Exists(p_sFilename))
        //        {
        //            FileTools.CreateFile(p_sFilename, true);
        //        }

        //        Stream stream = null;
        //        try
        //        {
        //            stream = File.Open(p_sFilename, FileMode.Create);
        //            XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
        //            xmlSerializer.Serialize(stream, p_oObjectToSerialize);
        //        }
        //        finally
        //        {
        //            if (stream != null)
        //                stream.Close();
        //        }
        //    }

        //    /// <summary>
        //    /// Serializes the specified filename.
        //    /// </summary>
        //    /// <typeparam name="T">Generic type which implements the ISerializable interface</typeparam>
        //    /// <param name="p_sFilename">The filename.</param>
        //    /// <param name="objectToSerialize">The object to serialize.</param>
        //    public static T XMLDeserialize<T>(string p_sFilename)
        //    {
        //        T objectToSerialize = default(T);
        //        Stream stream = null;
        //        try
        //        {
        //            stream = File.Open(p_sFilename, FileMode.Open);
        //            XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
        //            objectToSerialize = (T)xmlSerializer.Deserialize(stream);
        //        }
        //        catch (Exception ex)
        //        {
        //            LogManager.GetBusinessLogger().LogErrorFormat("Unable to Deserialize the file {0} in object type {1}. Exception : {2}", p_sFilename, typeof(T).Name, ex);
        //        }
        //        finally
        //        {
        //            if (stream != null)
        //                stream.Close();
        //        }
        //        return objectToSerialize;
        //    }
        //}




    }


}
